#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <string>
#include <mutex> //c++11内置了锁
using namespace std;

//int num = 0;
//
//void* thread_run(void* args)
//{
//    while(1)
//    {
//        num++;
//        sleep(1);
//        printf("I am new thread, num = %d\n", num);
//    }
//}
//
//int main()
//{
//    pthread_t tid;
//    pthread_create(&tid, NULL, thread_run, NULL);
//    while(1){
//        printf("I am main thread, num = %d\n", num);
//        sleep(2);
//    }
//    pthread_join(tid, NULL);
//}




//tickets是所谓的临界资源，tickets--不是原子性的
//为了让多个线程进行切换，线程什么时候切换（1.时间片到了，2.检测的时间点：从内核态到用户态）
//int tickets = 100;
//
//void* ThreadRotinue(void* args)
//{
//    int id = *(int*)args;
//    delete (int*)args;
//    //购票的时候，不能出现负数的情况
//    while(true){
//        if(tickets > 0){
//            usleep(10000);
//            //cout <<"我是 [" << id << "] 我要抢的票是：" << tickets << endl;
//            printf("我是[%d] 我抢的票是：%d\n", id, tickets);
//            tickets--;
//        }
//        else{
//            break;
//        }
//    }
//    
//}
//
//int main()
//{
//    pthread_t tid[5];
//    for(int i = 0; i < 5; i++){
//      int* id = new int(i);
//      pthread_create(tid + i, nullptr, ThreadRotinue, id);
//    }
//    for(int i = 0; i < 5; i++){
//       pthread_join(tid[i], nullptr);
//    }
//    return 0;
//}





//为了解决刚才的问题，我们需要对临界区进行加锁
class Ticket{
public:
    
    Ticket():tickets(1000)
    {
        pthread_mutex_init(&mtx, nullptr);
    }

    bool GetTicket()
    {
        bool res = true;
        //我要访问临界资源的时候，也就是tickets，需要先访问mtx，前提就是所以线程要先看到它
        //那么锁本身，是不是也是临界资源！！！
        //如何保证锁本身是安全的！！！原理：它是原子的
        //pthread_mutex_lock(&mtx);
        mymtx.lock();
        mymtx.lock();
        //执行这部分代码的执行流就是互斥的，串行执行的
        if(tickets > 0){
            usleep(1000);
            printf("我是[%lu] 我抢的票是：%d\n", pthread_self(), tickets);
            tickets--;
        }
        else{
            printf("票已经被抢空了!\n");
            res = false;
        }
        mymtx.unlock();
        //pthread_mutex_unlock(&mtx);
        return res;
    }

    ~Ticket()
    {
        pthread_mutex_destroy(&mtx);
    }
private:
    int tickets;
    pthread_mutex_t mtx; //系统级别的锁，原生新线程库
    mutex mymtx; //c++语言级别的锁
};

void* ThreadRotinue(void* args)
{
    Ticket* t = (Ticket*)args;
    while(true){
        if(!t->GetTicket()){
            break;            
        }
    }
}

int main()
{
    Ticket* t = new Ticket();
    pthread_t tid[5];
    for(int i = 0; i < 5; i++){
        pthread_create(tid + i, nullptr, ThreadRotinue, (void*)t);
    }
    for(int i = 0; i < 5; i++){
        pthread_join(tid[i], nullptr);
    }
    return 0;
}


